Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Node / ReticulumProjects / MeshChatX.git / files / tests / backend / test_crash_recovery.py

Displaying Raw • Download


tests/backend/test_crash_recovery.py 39b8d5fef81d42e77ebf39f5f8292d2afc643d04 (39b8d5fe) Text, 13.22 KB

Tff7b72import T7ee787io
Tff7b72import T7ee787os
Tff7b72import T7ee787shutil
Tff7b72import T7ee787sqlite3
Tff7b72import T7ee787sys
Tff7b72import T7ee787tempfile
Tff7b72import T7ee787unittest
Tff7b72from T7ee787unittestT7ee787.T7ee787mock Tff7b72import Te6edf3MagicMockTb4b4b4, Te6edf3patch

Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backendT7ee787.T7ee787recoveryT7ee787.T7ee787crash_recovery Tff7b72import Te6edf3CrashRecovery


Tff7b72class T56d364TestCrashRecoveryTb4b4b4(Te6edf3unittestTff7b72.Td2a8ffTestCaseTb4b4b4)Tb4b4b4:
Tff7b72def Td2a8ffsetUpTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8fftest_dir Tff7b72= Te6edf3tempfileTff7b72.Td2a8ffmkdtempTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffstorage_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8fftest_dirTb4b4b4, Ta5d6ff"Ta5d6ffstorageTa5d6ff"Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdb_path Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4, Ta5d6ff"Ta5d6fftest.dbTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffpublic_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8fftest_dirTb4b4b4, Ta5d6ff"Ta5d6ffpublicTa5d6ff"Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpublic_dirTb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpublic_dirTb4b4b4, Ta5d6ff"Ta5d6ffindex.htmlTa5d6ff"Tb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6fftestTa5d6ff"Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffrecovery Tff7b72= Te6edf3CrashRecoveryTb4b4b4(
Te6edf3storage_dirTff7b72=Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4,
Te6edf3database_pathTff7b72=Tff7b72selfTff7b72.Td2a8ffdb_pathTb4b4b4,
Te6edf3public_dirTff7b72=Tff7b72selfTff7b72.Td2a8ffpublic_dirTb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8fftearDownTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3shutilTff7b72.Td2a8ffrmtreeTb4b4b4(Tff7b72selfTff7b72.Td2a8fftest_dirTb4b4b4)

Tff7b72def Td2a8fftest_diagnosis_normalTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# Create a valid DB
Te6edf3conn Tff7b72= Te6edf3sqlite3Tff7b72.Td2a8ffconnectTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdb_pathTb4b4b4)
Te6edf3connTff7b72.Td2a8ffexecuteTb4b4b4(Ta5d6ff"Ta5d6ffCREATE TABLE test (id INTEGER PRIMARY KEY)Ta5d6ff"Tb4b4b4)
Te6edf3connTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)

Te6edf3output Tff7b72= Te6edf3ioTff7b72.Td2a8ffStringIOTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ffrun_diagnosisTb4b4b4(Te6edf3fileTff7b72=Te6edf3outputTb4b4b4)
Te6edf3report Tff7b72= Te6edf3outputTff7b72.Td2a8ffgetvalueTb4b4b4(Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ffOS:Ta5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ffPython:Ta5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ffStorage Path:Ta5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ffIntegrity: OKTa5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ffFrontend Status: Assets verifiedTa5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)

Tff7b72def Td2a8fftest_diagnosis_missing_storageTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3shutilTff7b72.Td2a8ffrmtreeTb4b4b4(Tff7b72selfTff7b72.Td2a8ffstorage_dirTb4b4b4)
Te6edf3output Tff7b72= Te6edf3ioTff7b72.Td2a8ffStringIOTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ffrun_diagnosisTb4b4b4(Te6edf3fileTff7b72=Te6edf3outputTb4b4b4)
Te6edf3report Tff7b72= Te6edf3outputTff7b72.Td2a8ffgetvalueTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ff[ERROR] Storage path does not existTa5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)

Tff7b72def Td2a8fftest_diagnosis_corrupt_dbTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72with Tffa657openTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdb_pathTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ffnot a sqlite databaseTa5d6ff"Tb4b4b4)

Te6edf3output Tff7b72= Te6edf3ioTff7b72.Td2a8ffStringIOTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ffrun_diagnosisTb4b4b4(Te6edf3fileTff7b72=Te6edf3outputTb4b4b4)
Te6edf3report Tff7b72= Te6edf3outputTff7b72.Td2a8ffgetvalueTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ff[ERROR] Database is unreadableTa5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)

Tff7b72def Td2a8fftest_diagnosis_missing_frontendTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3shutilTff7b72.Td2a8ffrmtreeTb4b4b4(Tff7b72selfTff7b72.Td2a8ffpublic_dirTb4b4b4)
Te6edf3output Tff7b72= Te6edf3ioTff7b72.Td2a8ffStringIOTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ffrun_diagnosisTb4b4b4(Te6edf3fileTff7b72=Te6edf3outputTb4b4b4)
Te6edf3report Tff7b72= Te6edf3outputTff7b72.Td2a8ffgetvalueTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ff[ERROR] Frontend directory is missingTa5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)

Tff7b72def Td2a8fftest_diagnosis_rns_missing_configTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3rns_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8fftest_dirTb4b4b4, Ta5d6ff"Ta5d6ffrns_missingTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ffupdate_pathsTb4b4b4(Te6edf3reticulum_config_dirTff7b72=Te6edf3rns_dirTb4b4b4)
Te6edf3output Tff7b72= Te6edf3ioTff7b72.Td2a8ffStringIOTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ffrun_diagnosisTb4b4b4(Te6edf3fileTff7b72=Te6edf3outputTb4b4b4)
Te6edf3report Tff7b72= Te6edf3outputTff7b72.Td2a8ffgetvalueTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ff[ERROR] Reticulum config directory does not existTa5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)

Tff7b72def Td2a8fftest_diagnosis_rns_log_extractionTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3rns_dir Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8fftest_dirTb4b4b4, Ta5d6ff"Ta5d6ffrns_logTa5d6ff"Tb4b4b4)
Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Te6edf3rns_dirTb4b4b4)
Te6edf3log_file Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3rns_dirTb4b4b4, Ta5d6ff"Ta5d6fflogfileTa5d6ff"Tb4b4b4)
Tff7b72with Tffa657openTb4b4b4(Te6edf3log_fileTb4b4b4, Ta5d6ff"Ta5d6ffwTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3fTb4b4b4:
Te6edf3fTff7b72.Td2a8ffwriteTb4b4b4(Ta5d6ff"Ta5d6ffLine 1Tffea00\nTa5d6ffLine 2Tffea00\nTa5d6ffERROR: Something went wrongTffea00\nTa5d6ff"Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ffupdate_pathsTb4b4b4(Te6edf3reticulum_config_dirTff7b72=Te6edf3rns_dirTb4b4b4)
Te6edf3output Tff7b72= Te6edf3ioTff7b72.Td2a8ffStringIOTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ffrun_diagnosisTb4b4b4(Te6edf3fileTff7b72=Te6edf3outputTb4b4b4)
Te6edf3report Tff7b72= Te6edf3outputTff7b72.Td2a8ffgetvalueTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ffRecent Log EntriesTa5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ff> [ALERT] ERROR: Something went wrongTa5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)

Tff7b72def Td2a8fftest_env_disableTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffenvironTb4b4b4[Ta5d6ff"Ta5d6ffMESHCHAT_NO_CRASH_RECOVERYTa5d6ff"Tb4b4b4] Tff7b72= Ta5d6ff"Ta5d6ff1Ta5d6ff"
Te6edf3recovery Tff7b72= Te6edf3CrashRecoveryTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertFalseTb4b4b4(Te6edf3recoveryTff7b72.Td2a8ffenabledTb4b4b4)
Tff7b72del Te6edf3osTff7b72.Td2a8ffenvironTb4b4b4[Ta5d6ff"Ta5d6ffMESHCHAT_NO_CRASH_RECOVERYTa5d6ff"Tb4b4b4]

Tff7b72def Td2a8fftest_handle_exception_formatTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# We don't want to actually sys.exit(1) in tests, so we mock it
Te6edf3original_exit Tff7b72= Te6edf3sysTff7b72.Td2a8ffexit
Te6edf3sysTff7b72.Td2a8ffexit Tff7b72= Tff7b72lambda Te6edf3xTb4b4b4: Tff7b72None

Te6edf3output Tff7b72= Te6edf3ioTff7b72.Td2a8ffStringIOTb4b4b4(Tb4b4b4)
T8b949e# Redirect stderr to our buffer
Te6edf3original_stderr Tff7b72= Te6edf3sysTff7b72.Td2a8ffstderr
Te6edf3sysTff7b72.Td2a8ffstderr Tff7b72= Te6edf3output

Tff7b72tryTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffSimulated error for testingTa5d6ff"Tb4b4b4)
Tff7b72except Tf85149ValueErrorTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ffhandle_exceptionTb4b4b4(Tff7b72*Te6edf3sysTff7b72.Td2a8ffexc_infoTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72finallyTb4b4b4:
Te6edf3sysTff7b72.Td2a8ffstderr Tff7b72= Te6edf3original_stderr
Te6edf3sysTff7b72.Td2a8ffexit Tff7b72= Te6edf3original_exit

Te6edf3report Tff7b72= Te6edf3outputTff7b72.Td2a8ffgetvalueTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ff!!! APPLICATION CRASH DETECTED !!!Ta5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ffType: ValueErrorTa5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ffMessage: Simulated error for testingTa5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ffProbabilistic Root Cause Analysis:Ta5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ffRecovery Suggestions:Ta5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)

Tff7b72def Td2a8fftest_heuristic_analysis_sqliteTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3exc_type Tff7b72= Tffa657typeTb4b4b4(Ta5d6ff"Ta5d6ffOperationalErrorTa5d6ff"Tb4b4b4, Tb4b4b4(Tf85149ExceptionTb4b4b4,Tb4b4b4)Tb4b4b4, Tb4b4b4{Tb4b4b4}Tb4b4b4)
Te6edf3exc_typeTff7b72.Td2a8ff__name__ Tff7b72= Ta5d6ff"Ta5d6ffsqlite3.OperationalErrorTa5d6ff"
Te6edf3exc_value Tff7b72= Tf85149ExceptionTb4b4b4(Ta5d6ff"Ta5d6ffno such table: configTa5d6ff"Tb4b4b4)
Te6edf3diagnosis Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6ffdb_typeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffmemoryTa5d6ff"Tb4b4b4}

Te6edf3causes Tff7b72= Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ff_analyze_causeTb4b4b4(Te6edf3exc_typeTb4b4b4, Te6edf3exc_valueTb4b4b4, Te6edf3diagnosisTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertTrueTb4b4b4(Tffa657lenTb4b4b4(Te6edf3causesTb4b4b4) Tff7b72> T79c0ff0Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertEqualTb4b4b4(Te6edf3causesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4]Tb4b4b4, Ta5d6ff"Ta5d6ffIn-Memory Database Sync FailureTa5d6ff"Tb4b4b4)

Tff7b72def Td2a8fftest_heuristic_analysis_asyncioTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Te6edf3exc_type Tff7b72= Tf85149RuntimeError
Te6edf3exc_value Tff7b72= Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffno current event loopTa5d6ff"Tb4b4b4)
Te6edf3diagnosis Tff7b72= Tb4b4b4{Tb4b4b4}

Te6edf3causes Tff7b72= Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ff_analyze_causeTb4b4b4(Te6edf3exc_typeTb4b4b4, Te6edf3exc_valueTb4b4b4, Te6edf3diagnosisTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertTrueTb4b4b4(Tffa657lenTb4b4b4(Te6edf3causesTb4b4b4) Tff7b72> T79c0ff0Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ffAsynchronous InitializationTa5d6ff"Tb4b4b4, Te6edf3causesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4]Tb4b4b4)

Tff7b72def Td2a8fftest_heuristic_analysis_oom_priorityTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Verify that low memory increases OOM probability even with other errors."""
Te6edf3exc_type Tff7b72= Te6edf3sqlite3Tff7b72.Td2a8ffOperationalError
Te6edf3exc_value Tff7b72= Te6edf3sqlite3Tff7b72.Td2a8ffOperationalErrorTb4b4b4(Ta5d6ff"Ta5d6ffdatabase is lockedTa5d6ff"Tb4b4b4)
T8b949e# Scenario: Low memory + DB error
Te6edf3diagnosis Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6fflow_memoryTa5d6ff"Tb4b4b4: Tff7b72TrueTb4b4b4, Ta5d6ff"Ta5d6ffavailable_mem_mbTa5d6ff"Tb4b4b4: T79c0ff10Tb4b4b4}

Te6edf3causes Tff7b72= Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ff_analyze_causeTb4b4b4(Te6edf3exc_typeTb4b4b4, Te6edf3exc_valueTb4b4b4, Te6edf3diagnosisTb4b4b4)
T8b949e# OOM should be prioritized or at least highly probable (85% in code)
Te6edf3oom_cause Tff7b72= Tffa657nextTb4b4b4(Tb4b4b4(Te6edf3c Tff7b72for Te6edf3c Tff7b72in Te6edf3causes Tff7b72if Ta5d6ff"Ta5d6ffOOMTa5d6ff" Tff7b72in Te6edf3cTb4b4b4[Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertIsNotNoneTb4b4b4(Te6edf3oom_causeTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertEqualTb4b4b4(Te6edf3oom_causeTb4b4b4[Ta5d6ff"Ta5d6ffprobabilityTa5d6ff"Tb4b4b4]Tb4b4b4, T79c0ff85Tb4b4b4)

Tff7b72def Td2a8fftest_heuristic_analysis_rns_missingTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Verify high confidence for missing RNS config."""
Te6edf3exc_type Tff7b72= Tf85149RuntimeError
Te6edf3exc_value Tff7b72= Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffReticulum could not startTa5d6ff"Tb4b4b4)
Te6edf3diagnosis Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6ffconfig_missingTa5d6ff"Tb4b4b4: Tff7b72TrueTb4b4b4}

Te6edf3causes Tff7b72= Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ff_analyze_causeTb4b4b4(Te6edf3exc_typeTb4b4b4, Te6edf3exc_valueTb4b4b4, Te6edf3diagnosisTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertEqualTb4b4b4(Te6edf3causesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4]Tb4b4b4, Ta5d6ff"Ta5d6ffMissing Reticulum ConfigurationTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertEqualTb4b4b4(Te6edf3causesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffprobabilityTa5d6ff"Tb4b4b4]Tb4b4b4, T79c0ff99Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(
Ta5d6ff"Ta5d6ffdeterministic manifold constraintsTa5d6ff"Tb4b4b4,
Te6edf3causesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffreasoningTa5d6ff"Tb4b4b4]Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8fftest_entropy_calculation_levelsTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Test how entropy reflects system disorder."""
T8b949e# Baseline stable state
Te6edf3stable_diag Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6fflow_memoryTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6ffconfig_missingTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4}
Te6edf3stable_entropyTb4b4b4, Te6edf3_ Tff7b72= Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ff_calculate_system_entropyTb4b4b4(Te6edf3stable_diagTb4b4b4)

T8b949e# Unstable state (one critical issue)
Te6edf3unstable_diag Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6fflow_memoryTa5d6ff"Tb4b4b4: Tff7b72TrueTb4b4b4, Ta5d6ff"Ta5d6ffconfig_missingTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4}
Te6edf3unstable_entropyTb4b4b4, Te6edf3_ Tff7b72= Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ff_calculate_system_entropyTb4b4b4(Te6edf3unstable_diagTb4b4b4)

T8b949e# Very unstable state (multiple critical issues)
Te6edf3very_unstable_diag Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6fflow_memoryTa5d6ff"Tb4b4b4: Tff7b72TrueTb4b4b4, Ta5d6ff"Ta5d6ffconfig_missingTa5d6ff"Tb4b4b4: Tff7b72TrueTb4b4b4}
Te6edf3very_unstable_entropyTb4b4b4, Te6edf3_ Tff7b72= Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ff_calculate_system_entropyTb4b4b4(
Te6edf3very_unstable_diagTb4b4b4,
Tb4b4b4)

T8b949e# Entropy should increase with more issues
Tff7b72selfTff7b72.Td2a8ffassertGreaterTb4b4b4(Te6edf3unstable_entropyTb4b4b4, Te6edf3stable_entropyTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertGreaterTb4b4b4(Te6edf3very_unstable_entropyTb4b4b4, Te6edf3unstable_entropyTb4b4b4)

T8b949e# Max entropy for 2 binary states is at p=0.5, but here we sum
T8b949e# p_unstable = 0.1 + 0.4 + 0.4 = 0.9.
T8b949e# p=0.9 has lower entropy than p=0.5, but higher than p=0.1.
T8b949e# p_stable=0.9 (stable) vs p_stable=0.5 (medium) vs p_stable=0.1 (unstable)
T8b949e# H(0.1) = 0.469, H(0.5) = 1.0, H(0.9) = 0.469
T8b949e# The current implementation:
T8b949e# stable: p_unstable=0.1 -> H=0.469
T8b949e# unstable: p_unstable=0.5 -> H=1.0
T8b949e# very unstable: p_unstable=0.9 -> H=0.469 (wait, mathematically yes, but logically?)
T8b949e# Actually for a "disorder" metric, we might want it to peak when things are most uncertain.
T8b949e# But in our context, we are showing entropy of the "State Predictability".

Tff7b72def Td2a8fftest_confidence_grounding_textTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Verify that reasoning text reflects grounding logic."""
T8b949e# High confidence scenario
Te6edf3exc_type Tff7b72= Tf85149RuntimeError
Te6edf3exc_value Tff7b72= Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffno current event loopTa5d6ff"Tb4b4b4)
Te6edf3diagnosis Tff7b72= Tb4b4b4{Tb4b4b4} T8b949e# probability 88% -> heuristic matching
Te6edf3causes_low Tff7b72= Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ff_analyze_causeTb4b4b4(Te6edf3exc_typeTb4b4b4, Te6edf3exc_valueTb4b4b4, Te6edf3diagnosisTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(
Ta5d6ff"Ta5d6ffprobabilistic heuristic matchingTa5d6ff"Tb4b4b4,
Te6edf3causes_lowTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffreasoningTa5d6ff"Tb4b4b4]Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)

T8b949e# Near-certainty scenario
Te6edf3diagnosis_certain Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6ffconfig_missingTa5d6ff"Tb4b4b4: Tff7b72TrueTb4b4b4}
Te6edf3causes_high Tff7b72= Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ff_analyze_causeTb4b4b4(
Te6edf3exc_typeTb4b4b4,
Te6edf3exc_valueTb4b4b4,
Te6edf3diagnosis_certainTb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ffhigh-confidence thresholdTa5d6ff"Tb4b4b4, Te6edf3causes_highTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffreasoningTa5d6ff"Tb4b4b4]Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tb4b4b4)

Tff7b72def Td2a8fftest_heuristic_analysis_lxmf_storageTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Test LXMF storage failure detection."""
Te6edf3exc_type Tff7b72= Tf85149RuntimeError
Te6edf3exc_value Tff7b72= Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffLXMF could not open storage directoryTa5d6ff"Tb4b4b4)
Te6edf3diagnosis Tff7b72= Tb4b4b4{Tb4b4b4}

Te6edf3causes Tff7b72= Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ff_analyze_causeTb4b4b4(Te6edf3exc_typeTb4b4b4, Te6edf3exc_valueTb4b4b4, Te6edf3diagnosisTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertEqualTb4b4b4(Te6edf3causesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4]Tb4b4b4, Ta5d6ff"Ta5d6ffLXMF Router Storage FailureTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertEqualTb4b4b4(Te6edf3causesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffprobabilityTa5d6ff"Tb4b4b4]Tb4b4b4, T79c0ff90Tb4b4b4)

Tff7b72def Td2a8fftest_heuristic_analysis_rns_identityTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Test Reticulum identity failure detection."""
Te6edf3exc_type Tff7b72= Tf85149Exception
Te6edf3exc_value Tff7b72= Tf85149ExceptionTb4b4b4(Ta5d6ff"Ta5d6ffReticulum Identity load failed: corrupt private keyTa5d6ff"Tb4b4b4)
Te6edf3diagnosis Tff7b72= Tb4b4b4{Tb4b4b4}

Te6edf3causes Tff7b72= Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ff_analyze_causeTb4b4b4(Te6edf3exc_typeTb4b4b4, Te6edf3exc_valueTb4b4b4, Te6edf3diagnosisTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertEqualTb4b4b4(Te6edf3causesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4]Tb4b4b4, Ta5d6ff"Ta5d6ffReticulum Identity Load FailureTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertEqualTb4b4b4(Te6edf3causesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffprobabilityTa5d6ff"Tb4b4b4]Tb4b4b4, T79c0ff95Tb4b4b4)

Tff7b72def Td2a8fftest_heuristic_analysis_interface_offlineTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Test interface offline detection."""
Te6edf3exc_type Tff7b72= Tf85149RuntimeError
Te6edf3exc_value Tff7b72= Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffReticulum startup failedTa5d6ff"Tb4b4b4)
Te6edf3diagnosis Tff7b72= Tb4b4b4{Ta5d6ff"Ta5d6ffactive_interfacesTa5d6ff"Tb4b4b4: T79c0ff0Tb4b4b4}

T8b949e# We need to trigger the rns_in_msg symptom as well
Te6edf3exc_value Tff7b72= Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffReticulum failed, no path availableTa5d6ff"Tb4b4b4)
Te6edf3causes Tff7b72= Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ff_analyze_causeTb4b4b4(Te6edf3exc_typeTb4b4b4, Te6edf3exc_valueTb4b4b4, Te6edf3diagnosisTb4b4b4)

Te6edf3offline_cause Tff7b72= Tffa657nextTb4b4b4(
Tb4b4b4(Te6edf3c Tff7b72for Te6edf3c Tff7b72in Te6edf3causes Tff7b72if Ta5d6ff"Ta5d6ffInterfaceTa5d6ff" Tff7b72in Te6edf3cTb4b4b4[Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4,
Tff7b72NoneTb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertIsNotNoneTb4b4b4(Te6edf3offline_causeTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertEqualTb4b4b4(Te6edf3offline_causeTb4b4b4[Ta5d6ff"Ta5d6ffprobabilityTa5d6ff"Tb4b4b4]Tb4b4b4, T79c0ff85Tb4b4b4)

Tff7b72def Td2a8fftest_advanced_math_outputTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e# We don't want to actually sys.exit(1) in tests, so we mock it
Te6edf3original_exit Tff7b72= Te6edf3sysTff7b72.Td2a8ffexit
Te6edf3sysTff7b72.Td2a8ffexit Tff7b72= Te6edf3MagicMockTb4b4b4(Tb4b4b4)

Te6edf3output Tff7b72= Te6edf3ioTff7b72.Td2a8ffStringIOTb4b4b4(Tb4b4b4)
T8b949e# Redirect stderr to our buffer
Te6edf3original_stderr Tff7b72= Te6edf3sysTff7b72.Td2a8ffstderr
Te6edf3sysTff7b72.Td2a8ffstderr Tff7b72= Te6edf3output

Tff7b72tryTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72raise Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffno current event loopTa5d6ff"Tb4b4b4)
Tff7b72except Tf85149RuntimeErrorTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ffhandle_exceptionTb4b4b4(Tff7b72*Te6edf3sysTff7b72.Td2a8ffexc_infoTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72finallyTb4b4b4:
Te6edf3sysTff7b72.Td2a8ffstderr Tff7b72= Te6edf3original_stderr
Te6edf3sysTff7b72.Td2a8ffexit Tff7b72= Te6edf3original_exit

Te6edf3report Tff7b72= Te6edf3outputTff7b72.Td2a8ffgetvalueTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ff[System Entropy:Ta5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ff[Deterministic Manifold Constraints:Ta5d6ff"Tb4b4b4, Te6edf3reportTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ffdeterministic manifold constraintsTa5d6ff"Tb4b4b4, Te6edf3reportTff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tb4b4b4)

Tff7b72def Td2a8fftest_heuristic_analysis_unsupported_pythonTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Test detection of unsupported Python versions."""
T8b949e# We need to simulate the sys.version_info check
Tff7b72with Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffsys.version_infoTa5d6ff"Tb4b4b4) Tff7b72as Te6edf3mock_versionTb4b4b4:
Te6edf3mock_versionTff7b72.Td2a8ffmajor Tff7b72= T79c0ff3
Te6edf3mock_versionTff7b72.Td2a8ffminor Tff7b72= T79c0ff9

Te6edf3exc_type Tff7b72= Tf85149AttributeError
Te6edf3exc_value Tff7b72= Tf85149AttributeErrorTb4b4b4(Ta5d6ff"Ta5d6ff'Ta5d6ffNoneTypeTa5d6ff'Ta5d6ff object has no attribute Ta5d6ff'Ta5d6ffxTa5d6ff'Ta5d6ff"Tb4b4b4)
Te6edf3diagnosis Tff7b72= Tb4b4b4{Tb4b4b4}

Te6edf3causes Tff7b72= Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ff_analyze_causeTb4b4b4(Te6edf3exc_typeTb4b4b4, Te6edf3exc_valueTb4b4b4, Te6edf3diagnosisTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertEqualTb4b4b4(Te6edf3causesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4]Tb4b4b4, Ta5d6ff"Ta5d6ffUnsupported Python EnvironmentTa5d6ff"Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertEqualTb4b4b4(Te6edf3causesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffprobabilityTa5d6ff"Tb4b4b4]Tb4b4b4, T79c0ff99Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(
Ta5d6ff"Ta5d6ffmissing standard library featuresTa5d6ff"Tb4b4b4,
Te6edf3causesTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4[Ta5d6ff"Ta5d6ffreasoningTa5d6ff"Tb4b4b4]Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8fftest_heuristic_analysis_legacy_kernelTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
T8b949e"""Test detection of legacy system/kernel limitations."""
Tff7b72with Tb4b4b4(
Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffplatform.systemTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Ta5d6ff"Ta5d6ffLinuxTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3patchTb4b4b4(Ta5d6ff"Ta5d6ffplatform.releaseTa5d6ff"Tb4b4b4, Te6edf3return_valueTff7b72=Ta5d6ff"Ta5d6ff3.10.0-1160.el7.x86_64Ta5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)Tb4b4b4:
Te6edf3exc_type Tff7b72= Tf85149RuntimeError
Te6edf3exc_value Tff7b72= Tf85149RuntimeErrorTb4b4b4(Ta5d6ff"Ta5d6ffkernel feature not availableTa5d6ff"Tb4b4b4)
Te6edf3diagnosis Tff7b72= Tb4b4b4{Tb4b4b4}

Te6edf3causes Tff7b72= Tff7b72selfTff7b72.Td2a8ffrecoveryTff7b72.Td2a8ff_analyze_causeTb4b4b4(Te6edf3exc_typeTb4b4b4, Te6edf3exc_valueTb4b4b4, Te6edf3diagnosisTb4b4b4)
Te6edf3legacy_cause Tff7b72= Tffa657nextTb4b4b4(
Tb4b4b4(Te6edf3c Tff7b72for Te6edf3c Tff7b72in Te6edf3causes Tff7b72if Ta5d6ff"Ta5d6ffLegacy SystemTa5d6ff" Tff7b72in Te6edf3cTb4b4b4[Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4]Tb4b4b4)Tb4b4b4,
Tff7b72NoneTb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertIsNotNoneTb4b4b4(Te6edf3legacy_causeTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertGreaterEqualTb4b4b4(Te6edf3legacy_causeTb4b4b4[Ta5d6ff"Ta5d6ffprobabilityTa5d6ff"Tb4b4b4]Tb4b4b4, T79c0ff80Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffassertInTb4b4b4(Ta5d6ff"Ta5d6ffKernel detected: 3.10Ta5d6ff"Tb4b4b4, Te6edf3legacy_causeTb4b4b4[Ta5d6ff"Ta5d6ffreasoningTa5d6ff"Tb4b4b4]Tb4b4b4)


Tff7b72if Tff7b72__name__ Tff7b72== Ta5d6ff"Ta5d6ff__main__Ta5d6ff"Tb4b4b4:
Te6edf3unittestTff7b72.Td2a8ffmainTb4b4b4(Tb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────